﻿using System;
using InstanceController.ConfigurationDAL;
using InstanceController.RolesPerfMonDAL;
using InstanceController.StateMachineDAL;
using InstanceController.WADPerformanceCountersDAL;
using Microsoft.WindowsAzure.ServiceRuntime;
using WADConfigureWebRole;

namespace InstanceConfigurer
{
	public partial class Configure : System.Web.UI.Page
	{
		#region These match the Instance Controller worker role
		public const string ActionIncrement = "Increment";
		public const string ActionDecrement = "Decrement";
		public const string ActionManual = "Manual";
		#endregion

		public static ConfigurationDataModel ConfigurationDataModel;

		protected void Page_Load(object sender, EventArgs e)
		{
			Master.Page.Title = "Configuration - Instance Controller Administration";
			if (IsPostBack) return;

			GetConfigurationSettings();
			TextBoxRoleName.Text = Global.AppSettings.ControlledRoleName;
		}

		protected void ButtonSave_Click(object sender, EventArgs e)
		{
			SaveConfigurationSettings();
		}

		protected void ButtonView_Click(object sender, EventArgs e)
		{
			GetConfigurationSettings();
		}

		protected void ButtonDelete_Click(object sender, EventArgs e)
		{
			DeleteConfigurationSettings();
		}

		protected void ButtonInitialize_Click(object sender, EventArgs e)
		{
			LabelError.Text = InitializePerformanceCountersConfigurationSettings();
		}

		protected void ButtonRemove_Click(object sender, EventArgs e)
		{
			LabelError.Text = WADPerformanceCountersDataMethods.ClearAllTableRows().ToString();
		}

		protected void ButtonClearLogs_Click(object sender, EventArgs e)
		{
			LabelError.Text = DeleteLogs();
		}

		/// <summary>
		/// Clears the text boxes.
		/// </summary>
		private void ClearTextBoxes()
		{
			LabelPartitionKey.Text = "Configuration not set.";
			LabelRowKey.Text = String.Empty;
			TextBoxSubscriptionID.Text = String.Empty;
			TextBoxCertificateThumbPrint.Text = String.Empty;
			//TextBoxHostedServiceName.Text = String.Empty;
			TextBoxStorageServiceName.Text = String.Empty;
			TextBoxRoleName.Text = String.Empty;
			TextBoxDeploymentID.Text = String.Empty;
			TextBoxMaxInstances.Text = "2";
			TextBoxMinInstances.Text = "1";
			TextBoxStepDown.Text = "1";
			TextBoxStepUp.Text = "1";
			RadioButton1.Checked = true;
			LabelError.Text = String.Empty;
		}

		/// <summary>
		/// Gets the configuration settings from Azure table storage.
		/// </summary>
		private void GetConfigurationSettings()
		{
			// If the read finds nothing it returns null.
			Global.ConfigurationDataModel = ConfigurationDataMethods.ReadRow(Global.ConfigurationDataModel.PartitionKey,
																			 Global.ConfigurationDataModel.RowKey);
			// If the Global.ConfigurationDataModel is null then create it.
			if (Global.ConfigurationDataModel == null)
			{
				Global.InitializeConfigurationDataModelObject();
				ClearTextBoxes();
				return; // retun now - no point trying to set values here.
			}

			LabelPartitionKey.Text = Global.ConfigurationDataModel.PartitionKey;
			LabelRowKey.Text = Global.ConfigurationDataModel.RowKey;
			LabelMode.Text = Global.ConfigurationDataModel.ManualMode ? "Manual Mode" : "Auto Instance Mode";
			TextBoxSubscriptionID.Text = Global.ConfigurationDataModel.SubscriptionID;
			TextBoxCertificateThumbPrint.Text = Global.ConfigurationDataModel.CertificateThumbPrint;
			//TextBoxHostedServiceName.Text = Global.ConfigurationDataModel.HostServiceName;
			TextBoxStorageServiceName.Text = Global.ConfigurationDataModel.StorageServiceName;
			TextBoxRoleName.Text = Global.ConfigurationDataModel.RoleName;
			TextBoxDeploymentID.Text = Global.ConfigurationDataModel.DeploymentID;
			TextBoxMaxInstances.Text = Global.ConfigurationDataModel.MaxInstances.ToString();
			TextBoxMinInstances.Text = Global.ConfigurationDataModel.MinInstances.ToString();
			TextBoxStepDown.Text = Global.ConfigurationDataModel.DecrementStepValue.ToString();
			TextBoxStepUp.Text = Global.ConfigurationDataModel.IncrementStepValue.ToString();
			if (Global.ConfigurationDataModel.Slot == null) return;
			var s = Global.ConfigurationDataModel.Slot;
			s = s.ToLower();
			if (s.StartsWith("s"))
				RadioButton1.Checked = true;
			else
				RadioButton2.Checked = true;

			//The view shows what is currentlly stored in the configuration.
			var counterSettingsDataModelRow = CounterSettingsDataMethods.Read(Global.ConfigurationDataModel.SubscriptionID,
			                                                                   PlugIn.ProcessorFriendlyName);
			if (counterSettingsDataModelRow == null) return;
			TextBoxTopTheshold.Text = counterSettingsDataModelRow.IncThreshold.ToString();
			TextBoxBottomThreshold.Text = counterSettingsDataModelRow.DecThreshold.ToString();
		}

		/// <summary>
		/// Saves the configuration settings and performance counters to Azure table storage.
		/// Performance counters are defined in code in the Global.asax.cs file which is where
		/// Azure Diagnostics are configrued and initialized.
		/// </summary>
		private void SaveConfigurationSettings()
		{

			if ((((String.IsNullOrEmpty(TextBoxSubscriptionID.Text) && String.IsNullOrEmpty(TextBoxCertificateThumbPrint.Text)) &&
				   String.IsNullOrEmpty(TextBoxStorageServiceName.Text)) && String.IsNullOrEmpty(TextBoxRoleName.Text)) && String.IsNullOrEmpty(TextBoxDeploymentID.Text))
			{
				LabelError.Text = "Configuration data is missing.";
				return;
			}

			TextBoxDeploymentID.Text = RoleEnvironment.DeploymentId;
			//TextBoxRoleName.Text = RoleEnvironment.CurrentRoleInstance.Role.Name;

			TextBoxRoleName.Text = Global.AppSettings.ControlledRoleName;
			Global.ConfigurationDataModel.SubscriptionID = TextBoxSubscriptionID.Text;
			Global.ConfigurationDataModel.CertificateThumbPrint = TextBoxCertificateThumbPrint.Text;
			Global.ConfigurationDataModel.HostServiceName = TextBoxStorageServiceName.Text;			//TextBoxHostedServiceName.Text;
			Global.ConfigurationDataModel.StorageServiceName = TextBoxStorageServiceName.Text;
			Global.ConfigurationDataModel.RoleName = TextBoxRoleName.Text;
			Global.ConfigurationDataModel.DeploymentID = TextBoxDeploymentID.Text;
			Global.ConfigurationDataModel.Slot = RadioButton1.Checked ? ServiceDeploymentSlot.Staging.ToString() : ServiceDeploymentSlot.Production.ToString();
			Global.ConfigurationDataModel.MaxInstances = Int32.Parse(TextBoxMaxInstances.Text);
			Global.ConfigurationDataModel.MinInstances = Int32.Parse(TextBoxMinInstances.Text);
			Global.ConfigurationDataModel.DecrementStepValue = Int32.Parse(TextBoxStepDown.Text);
			Global.ConfigurationDataModel.IncrementStepValue = Int32.Parse(TextBoxStepUp.Text);
			Global.ConfigurationDataModel.IsActive = true;
			if (ConfigurationDataMethods.UpdateConfiguration(Global.ConfigurationDataModel, true))
			{
				LabelError.Text = String.Empty;
				LabelPartitionKey.Text = Global.ConfigurationDataModel.PartitionKey;
				LabelRowKey.Text = Global.ConfigurationDataModel.RowKey;
			}
			else
				LabelError.Text = "Failed to save configuration.";

			//Can't set counters until there is a configuration.
			LabelError.Text = InitializePerformanceCountersConfigurationSettings();

		}

		/// <summary>
		/// Deletes the configuration settings. Method first deletes
		/// all associated performance counter settings.
		/// </summary>
		private void DeleteConfigurationSettings()
		{
			LabelError.Text = DeletePerformanceCountersConfigurationSettings();

			ConfigurationDataMethods.DeleteConfiguration(Global.ConfigurationDataModel, true);
			Global.ConfigurationDataModel = null;
			Global.InitializeConfigurationDataModelObject();
			ClearTextBoxes();
		}

		/// <summary>
		/// Deletes the logs.
		/// </summary>
		/// <returns></returns>
		private static string DeleteLogs()
		{
			string result = String.Empty;
			StateDataModel stateDataModel;
			stateDataModel = new StateDataModel(Global.ConfigurationDataModel.RowKey + "__" + ActionDecrement, "x"); //rowkey cannot be null
			if(!StateDataMethods.DeleteState(stateDataModel, true, true))
				result = "Delete Logs Decrement Group - No log data rows found.";

			stateDataModel = new StateDataModel(Global.ConfigurationDataModel.RowKey + "__" + ActionIncrement, "x");
			if (!StateDataMethods.DeleteState(stateDataModel, true, true))
				result += "Delete Logs Increment Group - No log data rows found.";

			stateDataModel = new StateDataModel(Global.ConfigurationDataModel.RowKey + "__" + ActionManual, "x");
			if (!StateDataMethods.DeleteState(stateDataModel, true, true))
				result += "Delete Logs ManualMode Group - No log data rows found.";

			return result;
		}

		/// <summary>
		/// Initializes the performance counters configuration settings. Creates/update the
		/// counter settings. The Instance Monitor evalues the setting in order of entry.
		/// </summary>
		/// <returns></returns>
		public string InitializePerformanceCountersConfigurationSettings()
		{
			string errors = String.Empty;
			// Looks up the configuration row and if found it creates/updates the performance counter metrics
			// If the read finds nothing it returns null.
			var configurationDataModel = ConfigurationDataMethods.ReadRow(Global.ConfigurationDataModel.PartitionKey, Global.ConfigurationDataModel.RowKey);

			if (configurationDataModel == null)
			{
				return "Failed - Could not find configuration data row.";
			}
			var settings = PlugIn.GetPerformanceCounterItems(); // defined data points of interest

			// Loops through the settings and creates/updates them in table storage
			foreach (var performanceCounterItem in settings)
			{
				CounterSettingsDataModel counterSettingsDataModel;
				if (!CheckBoxUseDefaults.Checked && performanceCounterItem.FriendlyName == PlugIn.ProcessorFriendlyName)
				{
					counterSettingsDataModel =
						new CounterSettingsDataModel(configurationDataModel.SubscriptionID, performanceCounterItem.FriendlyName)
							{
								CounterName = performanceCounterItem.CounterName,
								DecThreshold = Int32.Parse(TextBoxBottomThreshold.Text),
								IncThreshold = Int32.Parse(TextBoxTopTheshold.Text),
								PaddingSeconds = performanceCounterItem.PaddingSeconds,
								PriorityLevel = performanceCounterItem.PriorityLevel,
								PollingInterval = performanceCounterItem.PollingInterval
							};
				}
				else
				{
					// the friendlyname is used because the CounterName cannot be used as a rowKey due to illegal characters
					counterSettingsDataModel =
						new CounterSettingsDataModel(configurationDataModel.SubscriptionID, performanceCounterItem.FriendlyName)
							{
								CounterName = performanceCounterItem.CounterName,
								DecThreshold = performanceCounterItem.DecThreshold,
								IncThreshold = performanceCounterItem.IncThreshold,
								PaddingSeconds = performanceCounterItem.PaddingSeconds,
								PriorityLevel = performanceCounterItem.PriorityLevel,
								PollingInterval = performanceCounterItem.PollingInterval
							};
				}
				// Skip all settings where the PollingInterval is less than 1
				if (performanceCounterItem.PollingInterval >= 1)
				{
					// Since the item may be either an insert or update we can't really batch these
					if (!CounterSettingsDataMethods.UpdateCounterSettings(counterSettingsDataModel, true))
						errors += counterSettingsDataModel.CounterName + "\n\r";
				}
			}
			return errors;
		}

		/// <summary>
		/// Deletes the performance counters configuration settings. Removes permanetly all
		/// settings for the web role specified in the partition key.
		/// </summary>
		/// <returns></returns>
		public string DeletePerformanceCountersConfigurationSettings()
		{
			// Looks up the configuration row and if found it deletes the performance counter metrics
			// If the read finds nothing it returns null.
			var configurationDataModel = ConfigurationDataMethods.ReadRow(Global.ConfigurationDataModel.PartitionKey,
																			 Global.ConfigurationDataModel.RowKey);
			if (configurationDataModel == null)
				return "Failed - Could not find configuration data row.";

			var counterSettingsDataModel = new CounterSettingsDataModel(configurationDataModel.SubscriptionID, "x");
			return !CounterSettingsDataMethods.DeleteCounterSettings(counterSettingsDataModel, true, true)
					? "Delete Settings Group Failed - Could not find Counter Settings data rows."
					: String.Empty;
		}

		/// <summary>
		/// Deletes the specified performance counters configuration settings. Remove permanetly the
		/// specified setting for the web role specified in the partition key and row key.
		/// </summary>
		/// <param name="rowKey">The row key.</param>
		/// <returns></returns>
		public string DeleteSpecifiedPerformanceCountersConfigurationSettings(string rowKey)
		{
			// Looks up the configuration row and if found it deletes the performance counter metrics
			// If the read finds nothing it returns null.
			var configurationDataModel = ConfigurationDataMethods.ReadRow(Global.ConfigurationDataModel.PartitionKey,
																			 Global.ConfigurationDataModel.RowKey);
			if (configurationDataModel == null)
			{
				return "Failed - Could not find configuration data row.";
			}

			var counterSettingsDataModel =
				new CounterSettingsDataModel(configurationDataModel.RoleName, rowKey);

			if (!CounterSettingsDataMethods.DeleteCounterSettings(counterSettingsDataModel, true, false))
				return "Delete Settings Failed - Could not find Counter Settings data rows for. " + counterSettingsDataModel.CounterName;
			return String.Empty;
		}

	}
}
